﻿/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../global/head.h"
#include "node_impl.h"

namespace xos_xml
{
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static node_impl::POOL * pool_ptr = 0;

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    node_impl::node_impl()
    {
        init_data();
    }

    node_impl::~node_impl()
    {
        term();
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // public method

    int node_impl::get_addr( POOL *** pppPool, LIST *** pppList )
    {
        int ret = 0;
        if( pppPool )
        {
            *pppPool = &pool_ptr;
        }
        if( pppList )
        {
            *pppList = 0;
        }
        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // i_xml_node method

    // 
    // 返出指定名称的节点.
    // 
    int node_impl::select_single_node( const char * lpszNodeName, i_xml_node ** ppv )
    {
        int nRet = 0;

        TiXmlElement * pRet = 0;

        if( 0 == nRet )
        {
            if( !ppv )
            {
                nRet = 1;
            }
            else
            {
                *ppv = 0;
            }
        }

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            pRet = m_pNode->FirstChildElement( lpszNodeName );

            if( !pRet )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            node_impl * p = node_impl::get_item_from_pool( true );
            p->init();
            p->m_bHasOwner = false;
            p->m_pNode = pRet;
            *ppv = p;
        }

        return nRet;
    }

    // 
    // 将节点及之下内容保存成字串
    // 
    int node_impl::save_xml_string( char * lpszXml, int nLen, int * lpnLenNeeded )
    {
        using namespace std;

        int nRet = 0;

        TiXmlPrinter print;
        int nSize = 0;

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            print.SetIndent( "\t" );
            m_pNode->Accept( &print );

            nSize = ( int )print.Size();

            if( lpnLenNeeded )
            {
                *lpnLenNeeded = nSize + 1;
            }
        }

        if( 0 == nRet )
        {
            if( !lpszXml || ( nSize > nLen - 1 ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            g_pSysData->m_pContainer->crt()->strcpy( lpszXml, nLen, print.CStr() );
        }

        return nRet;
    }

    // 
    // 返出指定名称的节点.
    // 
    int node_impl::get_parent_node( i_xml_node ** ppv )
    {
        int nRet = 0;

        TiXmlNode * pRet = 0;

        if( 0 == nRet )
        {
            if( !ppv )
            {
                nRet = 1;
            }
            else
            {
                *ppv = 0;
            }
        }

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            pRet = m_pNode->Parent();

            if( !pRet )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            node_impl * p = node_impl::get_item_from_pool( true );
            p->init();
            p->m_bHasOwner = false;
            p->m_pNode = pRet->ToElement();
            *ppv = p;
        }

        return nRet;
    }

    int node_impl::get_child_node( i_xml_node ** ppv )
    {
        int nRet = 0;

        TiXmlElement * pRet = 0;

        if( 0 == nRet )
        {
            if( !ppv )
            {
                nRet = 1;
            }
            else
            {
                *ppv = 0;
            }
        }

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            pRet = m_pNode->FirstChildElement();

            if( !pRet )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            node_impl * p = node_impl::get_item_from_pool( true );
            p->init();
            p->m_bHasOwner = false;
            p->m_pNode = pRet;
            *ppv = p;
        }

        return nRet;
    }

    // 
    // 兄弟节点
    // 
    int node_impl::get_prev_sibling_node( i_xml_node ** ppv )
    {
        int nRet = 0;

        TiXmlNode * pRet = 0;

        if( 0 == nRet )
        {
            if( !ppv )
            {
                nRet = 1;
            }
            else
            {
                *ppv = 0;
            }
        }

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            pRet = m_pNode->PreviousSibling();

            if( !pRet )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            node_impl * p = node_impl::get_item_from_pool( true );
            p->init();
            p->m_bHasOwner = false;
            p->m_pNode = pRet->ToElement();
            *ppv = p;
        }

        return nRet;
    }

    int node_impl::get_next_sibling_node( i_xml_node ** ppv )
    {
        int nRet = 0;

        TiXmlElement * pRet = 0;

        if( 0 == nRet )
        {
            if( !ppv )
            {
                nRet = 1;
            }
            else
            {
                *ppv = 0;
            }
        }

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            pRet = m_pNode->NextSiblingElement();

            if( !pRet )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            node_impl * p = node_impl::get_item_from_pool( true );
            p->init();
            p->m_bHasOwner = false;
            p->m_pNode = pRet;
            *ppv = p;
        }

        return nRet;
    }

    int node_impl::get_node_prop( char * lpszName, int nNameLen, int * lpnNameLenNeed, char * lpszProp, int nPropLen, int * lpnPropLenNeed )
    {
        int ret = 0;

        if( ( 0 == ret ) && ( !m_pNode || !m_pAttribute ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            const char * value = m_pAttribute->Value();
            const char * name = m_pAttribute->Name();
            int value_len = g_pSysData->m_pContainer->crt()->strlen( value );
            int name_len = g_pSysData->m_pContainer->crt()->strlen( name );
            g_pSysData->m_pContainer->crt()->strcpy( lpszProp, nPropLen, value );
            g_pSysData->m_pContainer->crt()->strcpy( lpszName, nNameLen, name );
            if( lpnNameLenNeed )
            {
                *lpnNameLenNeed = name_len;
            }
            if( lpnPropLenNeed )
            {
                *lpnPropLenNeed = value_len;
            }
        }

        return ret;
    }

    int node_impl::get_node_prop( const char * lpszName, char * lpszProp, int nLen, int * lpnLenNeed )
    {
        int nRet = 0;

        const char * lpszAttr = 0;
        int len = 0;

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            if( !lpszName || ( 0 == strlen( lpszName ) ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            lpszAttr = m_pNode->Attribute( lpszName );

            if( !lpszAttr )
            {
                nRet = 1;
            }
            else
            {
                len = ( int )strlen( lpszAttr );
            }
        }

        if( 0 == nRet )
        {
            if( lpnLenNeed )
            {
                *lpnLenNeed = len;
            }

            if( lpszProp && ( nLen > len ) )
            {
                g_pSysData->m_pContainer->crt()->strcpy( lpszProp, nLen, lpszAttr );
            }
            else
            {
                nRet = 1;
            }
        }

        return nRet;
    }

    int node_impl::set_node_prop( const char * lpszName, const char * lpszProp )
    {
        int nRet = 0;

        if( 0 == nRet )
        {
            if( !m_pNode || !lpszProp || !lpszName )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            if( ( 0 == strlen( lpszName ) ) || ( 0 == strlen( lpszProp ) ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            m_pNode->SetAttribute( lpszName, lpszProp );
        }

        return nRet;
    }

    int node_impl::reset_property()
    {
        int ret = 0;

        const TiXmlAttribute * pAttribute = 0;

        if( ( 0 == ret ) && !m_pNode )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            pAttribute = m_pNode->FirstAttribute();
            if( pAttribute )
            {
                m_pAttribute = pAttribute;
            }
            else
            {
                ret = 1;
            }
        }

        return ret;
    }

    int node_impl::next_property()
    {
        int ret = 0;

        const TiXmlAttribute * pAttribute = 0;

        if( ( 0 == ret ) && ( !m_pNode || !m_pAttribute ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            pAttribute = m_pAttribute->Next();
            if( pAttribute )
            {
                m_pAttribute = pAttribute;
            }
            else
            {
                m_pAttribute = 0;
                ret = 1;
            }
        }

        return ret;
    }

    // 
    // 节点名称,属性
    // 
    int node_impl::get_node_name( char * lpszName, int nLen, int * lpnLenNeed )
    {
        int nRet = 0;

        const char * lpszNodeName = 0;
        int len = 0;

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            lpszNodeName = m_pNode->Value();

            if( !lpszNodeName )
            {
                nRet = 1;
            }
            else
            {
                len = ( int )strlen( lpszNodeName );
            }
        }

        if( 0 == nRet )
        {
            if( lpnLenNeed )
            {
                *lpnLenNeed = len;
            }

            if( lpszName && ( nLen > len ) )
            {
                g_pSysData->m_pContainer->crt()->strcpy( lpszName, nLen, lpszNodeName );
            }
            else
            {
                nRet = 1;
            }
        }

        return nRet;
    }

    int node_impl::set_node_name( const char * lpszName )
    {
        int nRet = 0;

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            if( !lpszName || ( 0 == strlen( lpszName ) ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            m_pNode->SetValue( lpszName );
        }

        return nRet;
    }

    int node_impl::get_node_value( char * lpszValue, int nLen, int * lpnLenNeed )
    {
        int nRet = 0;

        const char * lpszNodeValue = 0;
        int len = 0;

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            lpszNodeValue = m_pNode->GetText();

            if( !lpszNodeValue )
            {
                nRet = 1;
            }
            else
            {
                len = ( int )strlen( lpszNodeValue );
            }
        }

        if( 0 == nRet )
        {
            if( lpnLenNeed )
            {
                *lpnLenNeed = len;
            }

            if( lpszValue && ( nLen > len ) )
            {
                g_pSysData->m_pContainer->crt()->strcpy( lpszValue, nLen, lpszNodeValue );
            }
            else
            {
                nRet = 1;
            }
        }

        return nRet;
    }

    int node_impl::set_node_value( const char * lpszValue )
    {
        int nRet = 0;

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            if( !lpszValue || ( 0 == strlen( lpszValue ) ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            TiXmlText text( lpszValue );
            TiXmlNode * pLast = m_pNode->FirstChild();

            if( pLast )
            {
                m_pNode->ReplaceChild( pLast, text );
            }
            else
            {
                m_pNode->InsertEndChild( text );
            }
        }

        return nRet;
    }

    // 
    // 节点
    // 
    int node_impl::create_and_append_node( const char * lpszNodeName, i_xml_node ** ppv )
    {
        int nRet = 0;

        TiXmlNode * pNode = 0;

        if( 0 == nRet )
        {
            if( !ppv )
            {
                nRet = 1;
            }
            else
            {
                *ppv = 0;
            }
        }

        if( 0 == nRet )
        {
            if( !m_pNode || !lpszNodeName )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            if( 0 == strlen( lpszNodeName ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            pNode = m_pNode->InsertEndChild( TiXmlElement( lpszNodeName ) );

            if( !pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            node_impl * p = node_impl::get_item_from_pool( true );
            p->init();
            p->m_bHasOwner = false;
            p->m_pNode = pNode->ToElement();
            *ppv = p;
        }

        return nRet;
    }

    int node_impl::create_node( const char * lpszNodeName, i_xml_node ** ppv )
    {
        int nRet = 0;

        TiXmlElement * pNode = 0;

        if( 0 == nRet )
        {
            if( !ppv )
            {
                nRet = 1;
            }
            else
            {
                *ppv = 0;
            }
        }

        if( 0 == nRet )
        {
            if( !m_pNode || !lpszNodeName )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            if( 0 == strlen( lpszNodeName ) )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            pNode = new TiXmlElement( lpszNodeName );

            if( !pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            node_impl * p = node_impl::get_item_from_pool( true );
            p->init();
            p->m_bHasOwner = true;
            p->m_pNode = pNode;
            *ppv = p;
        }

        return nRet;
    }

    int node_impl::append_node( i_xml_node * pv )
    {
        int nRet = 0;

        TiXmlNode * pNode = 0;
        node_impl * p = 0;

        if( 0 == nRet )
        {
            if( !m_pNode || !pv )
            {
                nRet = 1;
            }
            else
            {
                p = static_cast< node_impl * >( pv );
            }
        }

        if( 0 == nRet )
        {
            pNode = m_pNode->LinkEndChild( p->m_pNode );

            if( pNode != p->m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            p->m_bHasOwner = false;
        }

        return nRet;
    }

    int node_impl::remove_node( i_xml_node * pv )
    {
        int nRet = 0;

        node_impl * p = 0;

        if( 0 == nRet )
        {
            if( !m_pNode || !pv )
            {
                nRet = 1;
            }
            else
            {
                p = static_cast< node_impl * >( pv );
            }
        }

        if( 0 == nRet )
        {
            bool bRet = m_pNode->RemoveChild( p->m_pNode );

            if( !bRet )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            p->m_bHasOwner = false;
            p->init();
        }

        return nRet;
    }

    // 
    // 克隆节点
    // 
    int node_impl::clone( i_xml_node ** ppv )
    {
        int nRet = 0;

        TiXmlElement * pItem = 0;
        TiXmlNode * pNode = 0;

        if( 0 == nRet )
        {
            if( !m_pNode )
            {
                nRet = 1;
            }
        }

        if( 0 == nRet )
        {
            pNode = m_pNode->Clone();

            if( !pNode )
            {
                nRet = 1;
            }
            else
            {
                pItem = pNode->ToElement();
            }
        }

        if( 0 == nRet )
        {
            node_impl * p = node_impl::get_item_from_pool( true );
            p->init();
            p->m_bHasOwner = true;
            p->m_pNode = pItem;
            *ppv = p;
        }

        return nRet;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int node_impl::init_data()
    {
        int nRet = 0;

        m_pAttribute = 0;
        m_bHasOwner = false;
        m_pNode = 0;

        return nRet;
    }

    int node_impl::init()
    {
        int nRet = 0;
        return nRet;
    }

    int node_impl::term()
    {
        int nRet = 0;

        if( m_bHasOwner && m_pNode )
        {
            // 必须以静态库方式使用tinyxml
            delete m_pNode;
            m_pNode = 0;
        }

        init_data();

        return nRet;
    }

} // xos_xml
